# 前言
本小节,我们将进入模版编译的最后一步:代码生成器 genetate。
generate(
ast,
extend({}, options, {
prefixIdentifiers
})
)
@前端进阶之旅: 代码已经复制到剪贴板
一起来看一下 generate 的核心实现:
export function generate(ast, options = {}) {
// 创建代码生成上下文
const context = createCodegenContext(ast, options)
const {
mode,
push,
prefixIdentifiers,
indent,
deindent,
newline,
scopeId,
ssr
} = context
const hasHelpers = ast.helpers.length > 0
const useWithBlock = !prefixIdentifiers && mode !== 'module'
const genScopeId = !__BROWSER__ && scopeId != null && mode === 'module'
const isSetupInlined = !__BROWSER__ && !!options.inline
// 生成预设代码
const preambleContext = isSetupInlined
? createCodegenContext(ast, options)
: context
// 不在浏览器的环境且 mode 是 module
if (!__BROWSER__ && mode === 'module') {
genModulePreamble(ast, preambleContext, genScopeId, isSetupInlined)
} else {
genFunctionPreamble(ast, preambleContext)
}
// 进入 render 函数构造
const functionName = `render`
const args = ['_ctx', '_cache']
const signature = args.join(', ')
push(`function ${functionName}(${signature}) {`)
indent()
if (useWithBlock) {
// 处理带 with 的情况,Web 端运行时编译
push(`with (_ctx) {`)
indent()
if (hasHelpers) {
push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = _Vue`)
push(`\n`)
newline()
}
}
// 生成自定义组件声明代码
if (ast.components.length) {
genAssets(ast.components, 'component', context)
if (ast.directives.length || ast.temps > 0) {
newline()
}
}
// 生成自定义指令声明代码